/*
 *    Copyright (c) 2018-2025, boss All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the boss developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: boss
 */
package com.hopes.bizz.poll.alarm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hopes.bizz.common.core.util.DateUtils;
import com.hopes.bizz.poll.alarm.bo.AlarmClassificationConfig;
import com.hopes.bizz.poll.alarm.bo.AlarmLevel;
import com.hopes.bizz.poll.alarm.entity.PollAlarmConfigEntity;
import com.hopes.bizz.poll.alarm.entity.PollAlarmHandleRecordEntity;
import com.hopes.bizz.poll.alarm.entity.PollAlarmNetEntity;
import com.hopes.bizz.poll.alarm.mapper.PollAlarmNetMapper;
import com.hopes.bizz.poll.alarm.message.AlarmMessageDistributor;
import com.hopes.bizz.poll.alarm.service.PollAlarmConfigService;
import com.hopes.bizz.poll.alarm.service.PollAlarmHandleRecordService;
import com.hopes.bizz.poll.alarm.service.PollAlarmNetService;
import com.hopes.bizz.poll.common.constant.AlarmConstant;
import com.hopes.bizz.poll.common.constant.OmConstant;
import com.hopes.bizz.poll.monitor.entity.PollMonitorSiteEntity;
import com.hopes.bizz.poll.monitor.service.PollMonitorSiteService;
import com.hopes.bizz.poll.om.entity.PollRtDataEntity;
import com.hopes.bizz.poll.om.service.PollRtDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 断网报警
 *
 * @author daijie
 * @date 2023-05-29 10:29:39
 */
@Service
public class PollAlarmNetServiceImpl extends ServiceImpl<PollAlarmNetMapper, PollAlarmNetEntity> implements PollAlarmNetService {
    @Autowired
    private PollAlarmConfigService configService;
    @Autowired
    @Lazy
    private PollMonitorSiteService pollMonitorSiteService;
    @Autowired
    @Lazy
    private PollRtDataService pollRtDataService;
    @Autowired
    @Lazy
    private PollAlarmHandleRecordService handleRecordService;

    @Override
    public Boolean alarmNetJobHandler() {
        // step.1 查询全部正在使用、在线采集的站点
        LambdaQueryWrapper<PollMonitorSiteEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(PollMonitorSiteEntity::getIsUse, true);
        wrapper.eq(PollMonitorSiteEntity::getIsOnline, true);
        List<PollMonitorSiteEntity> monitorSites = pollMonitorSiteService.list(wrapper);

        // step.2 查询分级报警全局配置
         LambdaQueryWrapper<PollAlarmConfigEntity> globalWrapper = Wrappers.lambdaQuery();
        globalWrapper.eq(PollAlarmConfigEntity::getDefaultFlag, true);
        PollAlarmConfigEntity globalConfig = configService.getOne(globalWrapper);

        Date now = new Date();
        for (PollMonitorSiteEntity monitorSite : monitorSites) {
            // step.3 查询当前站点是否有配置
            LambdaQueryWrapper<PollAlarmConfigEntity> configWrapper = Wrappers.lambdaQuery();
            configWrapper.eq(PollAlarmConfigEntity::getMonitorSiteId, monitorSite.getId());
            PollAlarmConfigEntity config = configService.getOne(configWrapper);

            // step.4 查询当前实时数据
            LambdaQueryWrapper<PollRtDataEntity> rtDataWrapper = Wrappers.lambdaQuery();
            rtDataWrapper.eq(PollRtDataEntity::getMonitorSiteId, monitorSite.getId());
            rtDataWrapper.eq(PollRtDataEntity::getDataType, OmConstant.DATA_TYPE_RT);
            PollRtDataEntity rtData = pollRtDataService.getOne(rtDataWrapper);

            // step.5 查询全部规则并按照级别从小到大排序
            List<AlarmLevel> alarmLevels;
            AlarmClassificationConfig netConfig;
            if (config == null || config.getNetConfig() == null) {
                netConfig = globalConfig.getNetConfig();
            } else if (!config.getNetConfig().getAlarmFlag()) {
                continue;
            } else {
                netConfig = config.getNetConfig();
            }
            alarmLevels = netConfig.getAlarmLevels().stream().filter(item->item.getAlarmLevel() != null)
                    .sorted(Comparator.comparing(AlarmLevel::getAlarmLevel)).collect(Collectors.toList());

            // 没有实时数据直接构造报警
            if (rtData == null) {
                saveOrUpdateAlarmNet(monitorSite, now, 0L, alarmLevels.get(alarmLevels.size() - 1));
                continue;
            }

            Date dataTime = rtData.getDataTime();
            Long min = DateUtils.getIntervalMin(dataTime, now);

            AlarmLevel finalLevel = null;
            for (AlarmLevel alarmLevel : alarmLevels) {
                if (alarmLevel.getLeft() < min) {
                    finalLevel = alarmLevel;
                }
            }
            if (finalLevel != null) {
                saveOrUpdateAlarmNet(monitorSite, now, min, finalLevel);
            } else {
                clearAlarmNetIfExist(monitorSite);
            }
        }
        return true;
    }

    private void saveOrUpdateAlarmNet(PollMonitorSiteEntity monitorSite, Date now, Long min, AlarmLevel alarmLevel) {
        // 是否已经有报警
        LambdaQueryWrapper<PollAlarmNetEntity> alarmNetWrapper = Wrappers.lambdaQuery();
        alarmNetWrapper.eq(PollAlarmNetEntity::getMonitorSiteId, monitorSite.getId());
        alarmNetWrapper.eq(PollAlarmNetEntity::getAlarmStatus, AlarmConstant.ALARM_STATUS_NOT);
        alarmNetWrapper.orderByDesc(PollAlarmNetEntity::getAlarmTime);
//        alarmNetWrapper.eq(PollAlarmNetEntity::getHandleStatus, AlarmConstant.ALARM_HANDLE_STATUS_NOT);
        PollAlarmNetEntity exist = this.getOne(alarmNetWrapper, false);

        if (exist != null) {
            Integer handleStatus = exist.getHandleStatus();
            if (handleStatus == AlarmConstant.ALARM_HANDLE_STATUS_NOT) {
                // 更新持续时间和报警级别
                exist.setDurationTime(min);
                exist.setAlarmLevel(alarmLevel.getAlarmLevel());
                exist.setAlarmContent(buildAlarmContent(exist.getAlarmTimeStr(), monitorSite.getName()));
                this.updateById(exist);
                return;
            } else if (handleStatus == AlarmConstant.ALARM_HANDLE_STATUS_ALREADY){
                LambdaQueryWrapper<PollAlarmHandleRecordEntity> recordWrapper = Wrappers.lambdaQuery();
                recordWrapper.eq(PollAlarmHandleRecordEntity::getModuleCode, AlarmConstant.ALARM_TYPE_NET);
                recordWrapper.eq(PollAlarmHandleRecordEntity::getAlarmId, exist.getId());
                recordWrapper.orderByDesc(PollAlarmHandleRecordEntity::getHandleTime);
                PollAlarmHandleRecordEntity record = handleRecordService.getOne(recordWrapper, false);
                if (record.getHandMovement() && record.getDeadline().after(new Date())) {
                    return;
                }
            }
        }
        // 新造报警
        PollAlarmNetEntity alarmNetEntity = new PollAlarmNetEntity();
        alarmNetEntity.setAlarmTime(now);
        alarmNetEntity.setDurationTime(min);
        alarmNetEntity.setAlarmLevel(alarmLevel.getAlarmLevel());
        alarmNetEntity.setAlarmStatus(AlarmConstant.ALARM_STATUS_NOT);
        alarmNetEntity.setHandleStatus(AlarmConstant.ALARM_HANDLE_STATUS_NOT);
        alarmNetEntity.setMonitorSiteId(monitorSite.getId());
        alarmNetEntity.setOrgId(monitorSite.getOrgId());

        alarmNetEntity.setAlarmContent(buildAlarmContent(alarmNetEntity.getAlarmTimeStr(), monitorSite.getName()));
        this.save(alarmNetEntity);

        AlarmMessageDistributor.broadcastMessage(alarmNetEntity.getAlarmContent());
    }

    private void clearAlarmNetIfExist(PollMonitorSiteEntity monitorSite) {
        // 是否已经有报警
        LambdaQueryWrapper<PollAlarmNetEntity> alarmNetWrapper = Wrappers.lambdaQuery();
        alarmNetWrapper.eq(PollAlarmNetEntity::getMonitorSiteId, monitorSite.getId());
        alarmNetWrapper.eq(PollAlarmNetEntity::getAlarmStatus, AlarmConstant.ALARM_STATUS_NOT);
        alarmNetWrapper.orderByDesc(PollAlarmNetEntity::getAlarmTime);
        PollAlarmNetEntity exist = this.getOne(alarmNetWrapper, false);

        // 消除报警
        if (exist != null) {
            exist.setAlarmStatus(AlarmConstant.ALARM_STATUS_ALREADY);
            exist.setRemoveTime(new Date());
            this.updateById(exist);
        }
    }

    private String buildAlarmContent(String date, String monitor) {
        StringBuilder sb = new StringBuilder("[断网]");
        sb.append("开始时间:").append(date);
        sb.append(", 监控点:").append(monitor);
        sb.append(", 请及时处理!");
        return sb.toString();
    }
}